import android.graphics.ImageFormat
import android.media.Image
import androidx.annotation.IntDef
import java.nio.ByteBuffer

//package com.jrfid.smartcabinet.demo.utils
//
//import androidx.camera.core.ImageAnalysis
//import androidx.camera.core.ImageProxy
//import android.annotation.SuppressLint
//import android.graphics.ImageFormat
//import android.media.Image.Plane
//import java.util.concurrent.locks.ReentrantLock
//
//class test : ImageAnalysis.Analyzer {
//    private var y: ByteArray? = null
//    private var u: ByteArray? = null
//    private var v: ByteArray? = null
//    private val lock = ReentrantLock()
//    private val mImageReaderLock: Any = 1 //1 available,0 unAvailable
//    private var lastDrawTime: Long = 0
//    private val timerSpace = 300 // 识别间隔
//    private var nv21: ByteArray? = null
//    override fun analyze(imageProxy: ImageProxy) {
//        @SuppressLint("UnsafeOptInUsageError") val mediaImage = imageProxy.image
//        //            int rotationDegrees = imageProxy.getImageInfo().getRotationDegrees();
//        if (mediaImage != null) {
//            synchronized(mImageReaderLock) {
//
//                /*识别频率Start 和状态*/
//                val start = System.currentTimeMillis()
//                if (start - lastDrawTime < timerSpace || mImageReaderLock != 1) {
//                    mediaImage.close()
//                    imageProxy.close()
//                    return
//                }
//                lastDrawTime = System.currentTimeMillis()
//                /*识别频率End*/
//
//                //判断YUV类型，我们申请的格式类型是YUV_420_888
//                if (ImageFormat.YUV_420_888 == mediaImage.format) {
//                    val planes = mediaImage.planes
//                    lock.lock()
//                    if (y == null) {
//                        y = ByteArray(planes[0].buffer.limit() - planes[0].buffer.position())
//                        u = ByteArray(planes[1].buffer.limit() - planes[1].buffer.position())
//                        v = ByteArray(planes[2].buffer.limit() - planes[2].buffer.position())
//                    }
//                    //从planes中分别获取y、u、v 变量数据
//                    if (mediaImage.planes[0].buffer.remaining() == y!!.size) {
//                        planes[0].buffer[y]
//                        planes[1].buffer[u]
//                        planes[2].buffer[v]
//                        if (nv21 == null) {
//                            nv21 = ByteArray(planes[0].rowStride * mediaImage.height * 3 / 2)
//                        }
//                        if (nv21!!.size != planes[0].rowStride * mediaImage.height * 3 / 2) {
//                            return
//                        }
//                        // 回传数据是YUV422
//                        if (y!!.size / u.size == 2) {
//                            ImageUtils.yuv422ToYuv420sp(y, u, v, nv21, planes[0].rowStride, mediaImage.height)
//                        } else if (y!!.size / u.size == 4) {
//                            nv21 = ImageUtils.yuv420ToNv21(mediaImage)
//                        }
//                    }
//                    lock.unlock()
//                }
//            }
//        }
//
//        //一定要关闭
//        mediaImage!!.close()
//        imageProxy.close()
//    }
//}

@kotlin.annotation.Retention(AnnotationRetention.SOURCE)

@IntDef(ImageFormat.NV21, ImageFormat.YUV_420_888)

annotation class YuvType

class YuvByteBuffer(image: Image, dstBuffer: ByteBuffer? = null) {
    @YuvType

    val type: Int

    val buffer: ByteBuffer

    init {
        val wrappedImage = ImageWrapper(image)

        type = if (wrappedImage.u.pixelStride == 1) {
            ImageFormat.YUV_420_888

        } else {
            ImageFormat.NV21

        }

        val size = image.width * image.height * 3 / 2

        buffer = if (dstBuffer == null || dstBuffer.isReadOnly || !dstBuffer.isDirect) {
            ByteBuffer.allocateDirect(size)
        } else {
            dstBuffer
        }
        buffer.rewind()
        removePadding(wrappedImage)
    }

// Input buffers are always direct as described in

// https://developer.android.com/reference/android/media/Image.Plane#getBuffer()

    private fun removePadding(image: ImageWrapper) {
        val sizeLuma = image.y.width * image.y.height

        val sizeChroma = image.u.width * image.u.height

        if (image.y.rowStride > image.y.width) {
            removePaddingCompact(image.y, buffer, 0)

        } else {
            buffer.position(0)

            buffer.put(image.y.buffer)

        }

        if (type == ImageFormat.YUV_420_888) {
            if (image.u.rowStride > image.u.width) {
                removePaddingCompact(image.u, buffer, sizeLuma)

                removePaddingCompact(image.v, buffer, sizeLuma + sizeChroma)

            } else {
                buffer.position(sizeLuma)

                buffer.put(image.u.buffer)

                buffer.position(sizeLuma + sizeChroma)

                buffer.put(image.v.buffer)

            }

        } else {
            if (image.u.rowStride > image.u.width * 2) {
                removePaddingNotCompact(image, buffer, sizeLuma)

            } else {
                buffer.position(sizeLuma)

                var uv = image.v.buffer

                val properUVSize = image.v.height * image.v.rowStride - 1

                if (uv.capacity() > properUVSize) {
                    uv = clipBuffer(image.v.buffer, 0, properUVSize)

                }

                buffer.put(uv)

                val lastOne = image.u.buffer[image.u.buffer.capacity() - 1]

                buffer.put(buffer.capacity() - 1, lastOne)

            }

        }

        buffer.rewind()

    }

    private fun removePaddingCompact(

        plane: PlaneWrapper,

        dst: ByteBuffer,

        offset: Int

    ) {
        require(plane.pixelStride == 1) {
            "use removePaddingCompact with pixelStride == 1"

        }

        val src = plane.buffer

        val rowStride = plane.rowStride

        var row: ByteBuffer

        dst.position(offset)

        for (i in 0 until plane.height) {
            row = clipBuffer(src, i * rowStride, plane.width)

            dst.put(row)

        }

    }

    private fun removePaddingNotCompact(

        image: ImageWrapper,

        dst: ByteBuffer,

        offset: Int

    ) {
        require(image.u.pixelStride == 2) {
            "use removePaddingNotCompact pixelStride == 2"

        }

        val width = image.u.width

        val height = image.u.height

        val rowStride = image.u.rowStride

        var row: ByteBuffer

        dst.position(offset)

        for (i in 0 until height - 1) {
            row = clipBuffer(image.v.buffer, i * rowStride, width * 2)

            dst.put(row)

        }

        row = clipBuffer(image.u.buffer, (height - 1) * rowStride - 1, width * 2)

        dst.put(row)

    }

    private fun clipBuffer(buffer: ByteBuffer, start: Int, size: Int): ByteBuffer {
        val duplicate = buffer.duplicate()

        duplicate.position(start)

        duplicate.limit(start + size)

        return duplicate.slice()

    }

    private class ImageWrapper(image: Image) {
        val width = image.width

        val height = image.height

        val y = PlaneWrapper(width, height, image.planes[0])

        val u = PlaneWrapper(width / 2, height / 2, image.planes[1])

        val v = PlaneWrapper(width / 2, height / 2, image.planes[2])

// Check this is a supported image format

// https://developer.android.com/reference/android/graphics/ImageFormat#YUV_420_888

        init {
            require(y.pixelStride == 1) {
                "Pixel stride for Y plane must be 1 but got ${y.pixelStride}instead."

            }

            require(u.pixelStride == v.pixelStride && u.rowStride == v.rowStride) {
                "U and V planes must have the same pixel and row strides " +

                        "but got pixel=${u.pixelStride} row=${u.rowStride} for U " +

                        "and pixel=${v.pixelStride} and row=${v.rowStride}for V"

            }

            require(u.pixelStride == 1 || u.pixelStride == 2) {
                "Supported" + " pixel strides for U and V planes are 1 and 2"

            }

        }

    }

    private class PlaneWrapper(width: Int, height: Int, plane: Image.Plane) {
        val width = width

        val height = height

        val buffer: ByteBuffer = plane.buffer

        val rowStride = plane.rowStride

        val pixelStride = plane.pixelStride

    }

}